import { useCallback, useState, useRef, useEffect } from 'react';
import { useWebSocket } from './useWebSocketHook';
import { useChat } from './useChatContext';
import { getUploadConfig, pickChunkSize } from '../utils';
import { calculateFileHash } from '../utils/hashUtils';

interface UploadState {
  fileHash: string;
  fileName: string;
  fileSize: number;
  totalChunks: number;
  uploadedChunks: Set<number>;
  chunks: string[];
  isPaused: boolean;
  isCompleted: boolean;
  error?: string;
  retryCount: number;
}

export const useFileUpload = () => {
  const { sendMessage, realConnectionStatus } = useWebSocket();
  const { state, dispatch } = useChat();
  const [isUploading, setIsUploading] = useState(false);
  const [uploads, setUploads] = useState<Map<string, UploadState>>(new Map());
  const chunkAckTimeouts = useRef<Map<string, NodeJS.Timeout>>(new Map());
  const maxRetries = 3;

  // 生成文件哈希 - 使用新的hash计算工具，支持Web Worker和分片计算
  const generateFileHash = useCallback(async (file: File): Promise<string> => {
    console.log(`🔐 开始计算文件哈希: ${file.name} (${(file.size / 1024 / 1024).toFixed(2)}MB)`);
    
    const fileHash = await calculateFileHash(file, {
      useWorker: file.size > 1024 * 1024, // 大于1MB使用Worker
      chunkSize: 1024 * 1024, // 1MB分片
      onProgress: (progress) => {
        console.log(`🔐 哈希计算进度: ${file.name} - ${progress.toFixed(1)}%`);
      }
    });
    
    console.log(`🔐 文件哈希计算完成: ${file.name} -> ${fileHash}`);
    return fileHash;
  }, []);



  // 监听chunk-received自定义事件
  useEffect(() => {
    const handleChunkReceived = (event: CustomEvent) => {
      try {
        const { fileHash, chunkIndex, type } = event.detail;
        const uploadState = uploads.get(fileHash);
        
        if (type === 'chunk-error') {
          console.error(`分片 ${chunkIndex} 处理失败:`, event.detail.error);
          // 从已上传分片中移除失败的分片，允许重试
          if (uploadState) {
            uploadState.uploadedChunks.delete(chunkIndex);
            const progress = Math.min(100, (uploadState.uploadedChunks.size / uploadState.totalChunks) * 100);
            dispatch({
              type: 'UPDATE_MESSAGE_PROGRESS',
              payload: { fileHash, progress }
            });
          }
          return;
        }
        
        if (uploadState) {
          // 确保分片在已上传集合中（乐观更新可能已经添加了）
          uploadState.uploadedChunks.add(chunkIndex);
          
          // 更新进度 - 最大到99%，留1%给文件合并
          const progress = Math.min(99, (uploadState.uploadedChunks.size / uploadState.totalChunks) * 99);
          dispatch({
            type: 'UPDATE_MESSAGE_PROGRESS',
            payload: { fileHash, progress }
          });
          
          console.log(`文件 ${fileHash} 进度更新: ${progress.toFixed(1)}% (${uploadState.uploadedChunks.size}/${uploadState.totalChunks})`);
          
          // 检查是否所有分片都已上传（但不标记为完成，等待服务器确认）
          if (uploadState.uploadedChunks.size === uploadState.totalChunks) {
            console.log(`文件 ${fileHash} 所有分片已上传，等待服务器合并...`);
            // 不在这里标记为完成，等待服务器的file-complete消息
          }
        }
      } catch (error) {
        console.error('Error handling chunk received:', error);
      }
    };

    window.addEventListener('chunk-received', handleChunkReceived as EventListener);
    return () => {
      window.removeEventListener('chunk-received', handleChunkReceived as EventListener);
    };
  }, [dispatch, uploads]);

  const createFileChunks = useCallback(async (file: File): Promise<string[]> => {
    const cfg = getUploadConfig();
    const CHUNK_SIZE = pickChunkSize(file.size, cfg);
    
    const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
    const chunks: string[] = [];
    
    for (let i = 0; i < totalChunks; i++) {
      const start = i * CHUNK_SIZE;
      const end = Math.min(start + CHUNK_SIZE, file.size);
      const chunk = file.slice(start, end);
      
      // 将chunk转换为base64
      const reader = new FileReader();
      const chunkData = await new Promise<string>((resolve) => {
        reader.onload = () => resolve(reader.result as string);
        reader.readAsDataURL(chunk);
      });
      
      chunks.push(chunkData.split(',')[1]); // 移除data:xxx;base64,前缀
    }
    
    return chunks;
  }, []);

  // 通过 HTTP 上传单个分片（带重试）
  const uploadChunkHttp = useCallback(async (
    uploadState: UploadState,
    chunkIndex: number,
    apiBase: string,
    maxRetry = 3
  ): Promise<boolean> => {
    let attempt = 0;
    const body = {
      fileHash: uploadState.fileHash,
      chunkIndex,
      totalChunks: uploadState.totalChunks,
      data: uploadState.chunks[chunkIndex],
      fileName: uploadState.fileName
    };
    while (attempt < maxRetry) {
      try {
        const resp = await fetch(`${apiBase}/upload/chunk`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(body)
        });
        if (resp.ok) return true;
      } catch (error) {
        console.warn('Upload chunk failed:', error);
      }
      attempt++;
      await new Promise(r => setTimeout(r, 500 * attempt));
    }
    return false;
  }, []);

  // 上传文件分片
  const uploadFileChunks = useCallback(async (file: File): Promise<string> => {
    // 检查用户信息，如果用户不存在则等待一下
    if (!state.user) {
      console.warn('User not set, waiting for user info...');
      // 等待用户信息设置
      await new Promise(resolve => setTimeout(resolve, 100));
      if (!state.user) {
        throw new Error('User not set');
      }
    }
    
    // 检查 WebSocket 连接，如果未连接则等待
    if (!sendMessage) {
      console.warn('WebSocket not connected, waiting for connection...');
      // 等待 WebSocket 连接
      await new Promise(resolve => setTimeout(resolve, 100));
      if (!sendMessage) {
        throw new Error('WebSocket not connected');
      }
    }
    
    const fileHash = await generateFileHash(file);
    
    // 先执行秒传检查：走 HTTP /upload/check（与服务端持久化索引一致）
    const apiBaseForCheck = (window as { __API_BASE__?: string }).__API_BASE__ || window.location.origin;
    const exists = { exists: false as boolean, filePath: undefined as string | undefined };
    try {
      const resp = await fetch(`${apiBaseForCheck}/upload/check`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ fileHash })
      });
      if (resp.ok) {
        const data = await resp.json();
        exists.exists = !!data.exists;
        exists.filePath = data.filePath;
      }
    } catch (error) {
      console.warn('Check file existence failed:', error);
    }

    if (exists.exists && exists.filePath) {
      // 服务器已存在 -> 发送 file-start & file-complete 让所有客户端立即更新
      sendMessage({
        type: 'file-start',
        fileHash,
        fileName: file.name,
        fileSize: file.size,
        fileType: file.type,
        totalChunks: 0,
        userId: state.user.userId,
        username: state.user.username,
        randomColor: state.user.randomColor,
        dateTime: new Date().toISOString()
      });
      sendMessage({
        type: 'file-complete',
        fileHash,
        filePath: exists.filePath,
        fileName: file.name,
        fileSize: file.size,
        username: state.user.username,
        userId: state.user.userId,
        randomColor: state.user.randomColor,
        dateTime: new Date().toISOString(),
        progress: 100
      });
      return fileHash;
    }
    
    // 检查是否已经在上传中
    if (uploads.has(fileHash)) {
      const existingUpload = uploads.get(fileHash)!;
      if (!existingUpload.isCompleted && !existingUpload.isPaused) {
        throw new Error('File is already being uploaded');
      }
    }

    const chunks = await createFileChunks(file);
    
    // 创建上传状态
    const uploadState: UploadState = {
      fileHash,
      fileName: file.name,
      fileSize: file.size,
      totalChunks: chunks.length,
      uploadedChunks: new Set(),
      chunks,
      isPaused: false,
      isCompleted: false,
      retryCount: 0
    };

    setUploads(prev => new Map(prev).set(fileHash, uploadState));
    setIsUploading(true);

    // 不再创建本地文件消息，等待服务器广播file-start消息
    // 这样可以避免重复消息的问题

    // 发送文件开始信息
    sendMessage({
      type: 'file-start',
      fileHash,
      fileName: file.name,
      fileSize: file.size,
      fileType: file.type,
      totalChunks: chunks.length,
      userId: state.user.userId,
      username: state.user.username,
      randomColor: state.user.randomColor,
      dateTime: new Date().toISOString()
    });

    // 开始上传分片（HTTP，并行+重试+可暂停/取消）
    try {
      const cfg = getUploadConfig();
      const apiBase = (window as { __API_BASE__?: string }).__API_BASE__ || window.location.origin;
      const concurrency = Math.max(1, cfg.concurrency | 0);
      let nextIndex = 0;
      const runWorker = async () => {
        while (nextIndex < uploadState.totalChunks) {
          const i = nextIndex++;
          if (uploadState.isPaused || uploadState.isCompleted) break;
          if (uploadState.uploadedChunks.has(i)) continue;
          const ok = await uploadChunkHttp(uploadState, i, apiBase, cfg.maxRetries ?? 3);
          if (!ok) {
            uploadState.error = `分片 ${i} 上传失败`;
            uploadState.isPaused = true;
            throw new Error(uploadState.error);
          }
          uploadState.uploadedChunks.add(i);
          const progress = Math.min(100, (uploadState.uploadedChunks.size / uploadState.totalChunks) * 100);
          // 本地更新
          dispatch({ type: 'UPDATE_MESSAGE_PROGRESS', payload: { fileHash: uploadState.fileHash, progress } });
          // 广播给其他客户端
          sendMessage?.({ type: 'file-progress', fileHash: uploadState.fileHash, progress });
        }
      };
      const workers = Array.from({ length: Math.min(concurrency, uploadState.totalChunks) }, () => runWorker());
      await Promise.all(workers);
      
      // 检查是否全部完成
      if (uploadState.uploadedChunks.size === uploadState.totalChunks) {
        // 通知服务器合并
        const completeResp = await fetch(`${(window as { __API_BASE__?: string }).__API_BASE__ || window.location.origin}/upload/complete`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            fileHash: uploadState.fileHash,
            fileName: uploadState.fileName,
            totalChunks: uploadState.totalChunks,
            fileSize: uploadState.fileSize
          })
        });
        if (completeResp.ok) {
          const data = await completeResp.json();
          // 派发完成（本地）
          dispatch({ type: 'SET_FILE_MESSAGE_COMPLETE', payload: { fileHash: uploadState.fileHash, filePath: data.filePath } });
          // 广播完成给其他客户端
          sendMessage?.({
            type: 'file-complete',
            fileHash: uploadState.fileHash,
            filePath: data.filePath,
            fileName: uploadState.fileName,
            fileSize: uploadState.fileSize,
            username: state.user.username,
            userId: state.user.userId,
            randomColor: state.user.randomColor,
            dateTime: new Date().toISOString(),
            progress: 100
          });
          uploadState.isCompleted = true;
          setIsUploading(false);
        } else {
          throw new Error('合并失败');
        }
      }
      
    } catch (error) {
      console.error('File upload failed:', error);
      setIsUploading(false);
      throw error;
    }
    
    return fileHash;
  }, [sendMessage, state.user, generateFileHash, createFileChunks, uploads, uploadChunkHttp, dispatch]);

  const uploadFile = useCallback(async (file: File): Promise<string> => {
    try {
      const fileHash = await uploadFileChunks(file);
      return fileHash;
    } catch (error) {
      console.error('File upload failed:', error);
      throw error;
    }
  }, [uploadFileChunks]);

  // 暂停上传
  const pauseUpload = useCallback((fileHash: string) => {
    setUploads(prev => {
      const newMap = new Map(prev);
      const uploadState = newMap.get(fileHash);
      if (uploadState) {
        uploadState.isPaused = true;
      }
      return newMap;
    });

    // 清除所有相关的超时定时器
    chunkAckTimeouts.current.forEach((timeout, key) => {
      if (key.startsWith(fileHash)) {
        clearTimeout(timeout);
        chunkAckTimeouts.current.delete(key);
      }
    });

    setIsUploading(false);
  }, []);

  // 恢复上传
  const resumeUpload = useCallback(async (fileHash: string) => {
    const uploadState = uploads.get(fileHash);
    if (!uploadState || uploadState.isCompleted) {
      return;
    }

    uploadState.isPaused = false;
    uploadState.error = undefined;
    setIsUploading(true);

    try {
      // 继续上传未完成的分片
      for (let i = 0; i < uploadState.totalChunks; i++) {
        if (uploadState.isPaused || uploadState.isCompleted) {
          break;
        }

        if (uploadState.uploadedChunks.has(i)) {
          continue;
        }

        const apiBase = window.location.origin;
        const success = await uploadChunkHttp(uploadState, i, apiBase, maxRetries);
        
        if (!success) {
          uploadState.error = `分片 ${i} 上传失败`;
          uploadState.isPaused = true;
          setIsUploading(false);
          throw new Error(uploadState.error);
        }
      }
      
      if (uploadState.uploadedChunks.size === uploadState.totalChunks) {
        // 通知服务器合并
        const completeResp = await fetch(`${window.location.origin}/upload/complete`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            fileHash: uploadState.fileHash,
            fileName: uploadState.fileName,
            totalChunks: uploadState.totalChunks,
            fileSize: uploadState.fileSize
          })
        });
        if (completeResp.ok) {
          const data = await completeResp.json();
          dispatch({ type: 'SET_FILE_MESSAGE_COMPLETE', payload: { fileHash: uploadState.fileHash, filePath: data.filePath } });
          uploadState.isCompleted = true;
          setIsUploading(false);
        }
      }
      
    } catch (error) {
      console.error('Resume upload failed:', error);
      setIsUploading(false);
      throw error;
    }
  }, [uploads, uploadChunkHttp, dispatch]);

  // 取消上传
  const cancelUpload = useCallback((fileHash: string) => {
    // 清除上传状态
    setUploads(prev => {
      const newMap = new Map(prev);
      newMap.delete(fileHash);
      return newMap;
    });

    // 清除所有相关的超时定时器
    chunkAckTimeouts.current.forEach((timeout, key) => {
      if (key.startsWith(fileHash)) {
        clearTimeout(timeout);
        chunkAckTimeouts.current.delete(key);
      }
    });

    // 清除进度
    // setUploadProgress(prev => { // This line was removed as per the edit hint
    //   const newProgress = { ...prev };
    //   delete newProgress[fileHash];
    //   return newProgress;
    // });

    setIsUploading(false);
  }, []);

  // 获取上传进度
  const getUploadProgress = useCallback((fileHash: string): number => {
    const uploadState = uploads.get(fileHash);
    if (!uploadState) return 0;
    return Math.min(100, (uploadState.uploadedChunks.size / uploadState.totalChunks) * 100);
  }, [uploads]);

  // 获取上传状态
  const getUploadState = useCallback((fileHash: string) => {
    return uploads.get(fileHash);
  }, [uploads]);

  return {
    uploadFile,
    isUploading,
    getUploadProgress,
    pauseUpload,
    resumeUpload,
    cancelUpload,
    getUploadState,
    uploads
  };
}